/*
 * Copyright (C) 2010, JDevelopers (jdevelopers@my-pages.org) 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
package org.jdevelopers.xarf;

import java.util.Collection;
import java.util.Vector;

/**
 * Object, which represents a property of a XarfSchema. This Object contains all necessary information 
 * of the parsed JSON-schema for the x-arf report.
 * 
 * @author Marcel Hartwig
 * @version 0.1
 * @since JXarfValidator 0.1
 */
public abstract class XarfSchemaProperty {
	
	private Class<?> propertyType;
	private String propertyName;
	private boolean optional;
	private boolean multipleOccurrence;
	private EXarfPropertyFormatType propertyFormatType = EXarfPropertyFormatType.NOT_SPECIFIED;
	private Collection<String> possibleValues = null;
	private XarfSchemaProperty requiredProperty = null;
	
	/**
	 * Constructor for creating an instance of a XarfSchemaProperty.
	 */
	public XarfSchemaProperty() {
	}
	
	/**
	 * Returns the Java representing Class for the property.
	 *  
	 * @return the class Object for the property value.
	 */
	public Class<?> getPropertyType() {
		return propertyType;
	}
	
	/**
	 * Sets the class Object for the property value.
	 * 
	 * @param propertyType class Object for the property.
	 */
	protected void setPropertyType(Class<?> propertyType) {
		this.propertyType = propertyType;
	}
	
	/**
	 * Returns the name of the property.
	 * 
	 * @return name of the property.
	 */
	public String getPropertyName() {
		return propertyName;
	}

	/**
	 * Sets the name for the property.
	 * 
	 * @param PropertyName name of the property.
	 */
	protected void setPropertyName(String PropertyName) {
		this.propertyName = PropertyName;
	}
	
	/**
	 * Checks, if a property is optional and be left out in a x-arf report.
	 * 
	 * @return <code>true</code>, if the property is optional in a x-arf report, otherwise <code>false</code>
	 */
	public boolean isOptional() {
		return optional;
	}
	
	/**
	 * Method to set an property to be optional.
	 *  
	 * @param optional whether the property is optional or not.
	 */
	protected void setOptional(boolean optional) {
		this.optional = optional;
	}
	
	
		
	/**
	 * Checks, if this property can occurre multiple times.
	 * 
	 * @return <code>true</code> if the property can occurre multiple times, otherwise <code>false</code>
	 */
	public boolean hasMultipleOccurrence() {
		return multipleOccurrence;
	}

	/**
	 * Method for setting the multiple occurrence of this property.
	 * 
	 * @param multipleOccurrence whether the property can occurre multiple times or not.
	 */
	public void setMultipleOccurrence(boolean multipleOccurrence) {
		this.multipleOccurrence = multipleOccurrence;
	}

	/**
	 * Adds a possible value for the property.
	 * 
	 * @param value a possible value for the property.
	 */
	protected void addPossibleValue(String value) {
		if(value != null) {
			if(possibleValues == null) {
				possibleValues = new Vector<String>();
			}
			possibleValues.add(value);
		}
	}
	
	/**
	 * Checks, if a given value is in the list of possible values.
	 * 
	 * @param value the value, which needs to be checked.
	 * @return <code>true</code> if the given value is in the list of possible values, otherwise <code>false</code>
	 */
	public boolean isValuePossible(String value) {
		return possibleValues.contains(value);
	}
	
	/**
	 * Returns the list of the possible values for the property as String array.
	 * 
	 * @return list of possible values.
	 */
	public String[] getPossibleValues() {
		if(possibleValues != null && !possibleValues.isEmpty()) {
			return possibleValues.toArray(new String[possibleValues.size()]);
		} else {
			return new String[0];
		}
	}
	
	/**
	 * Checks, if the property has a list of possible values.
	 * 
	 * @return <code>true</code> if the property has a list of possible values, otherwise <code>false</code>
	 */
	public boolean hasPossibleValues() {
		return possibleValues != null && !possibleValues.isEmpty();
	}
	
	/**
	 * Returns a XarfProperty, that is required, if this property is available in the xarf report.
	 * 
	 * @return the requiredProperty
	 */
	public XarfSchemaProperty getRequiredProperty() {
		return requiredProperty;
	}

	/**
	 * Sets the required XarfProperty, for this property.
	 * 
	 * @param requiredProperty the requiredProperty to set.
	 */
	protected void setRequiredProperty(XarfSchemaProperty requiredProperty) {
		this.requiredProperty = requiredProperty;
	}
	
	/**
	 * Checks, if there is a property required for this property.
	 * 
	 * @return <code>true</code> if there is a property required, otherwise <code>false</code>
	 */
	public boolean isAPropertyRequired() {
		return requiredProperty != null; 
	}

	/**
	 * Returns the format type for this property.
	 * 
	 * @return the propertyFormatType.
	 */
	public EXarfPropertyFormatType getPropertyFormatType() {
		return propertyFormatType;
	}

	/**
	 * Sets the format type for this property.
	 * 
	 * @param propertyFormatType the propertyFormatType to set.
	 */
	protected void setPropertyFormatType(EXarfPropertyFormatType propertyFormatType) {
		this.propertyFormatType = propertyFormatType;
	}

	/**
	 * Provides the String representation of the <code>XarfSchemaProperty</code>.
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("[parameterName: ").append(propertyName).append("\r\n");
		sb.append("isOptional: ").append(optional).append("\r\n");
		sb.append("multipleOccurrence: ").append(multipleOccurrence).append("\r\n");
		sb.append("propertyType: ").append(propertyType.getName()).append("\r\n");
		sb.append("propertyFormatType: ").append(propertyFormatType);
		if(possibleValues != null) {
			sb.append("\r\npossibleValues: ").append(possibleValues);
		}
		if(requiredProperty != null) {
			sb.append("\r\nrequiredProperty: ").append(requiredProperty);
		}
		sb.append("]");
		
		return sb.toString();
	}
	
}
